package com.example.yichuangyun.http;

import android.annotation.SuppressLint;
import android.util.Log;

import com.example.yichuangyun.BuildConfig;
import com.example.yichuangyun.application.MyApplication;
import com.example.yichuangyun.config.Constant;
import com.example.yichuangyun.model.EventBusModel;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Retrofit工具类
 */
public class RetrofitHelper {

    private static final String TAG = "RetrofitHelper";
    private static ApiService apiService;

    private RetrofitHelper() {
        init();
    }

    private void init() {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(msg -> {
            String message = null;
            try {//需判断json是什么格式
                if (msg.startsWith("{")) {
                    JSONObject jsonObject = new JSONObject(msg);
                    //最重要的方法，就一行，返回格式化的json字符串，其中的数字4是缩进字符数
                    message = jsonObject.toString(4);
                } else if (msg.startsWith("[")) {
                    JSONArray jsonArray = new JSONArray(msg);
                    message = jsonArray.toString(4);
                } else {
                    message = msg;
                }
            } catch (JSONException e) {
                message = msg;
            }
            Log.e(TAG, message);
            if (message.contains("\"result\": 201")) {
                if (!Constant.isLogout) {
                    EventBus.getDefault().post(new EventBusModel(Constant.logout));
                    Constant.isLogout = true;
                }
            }
        });
        loggingInterceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);

        @SuppressLint({"CustomX509TrustManager", "TrustAllX509TrustManager"})
        X509TrustManager xtm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };

        SSLContext sslContext;
        SSLSocketFactory sslSocketFactory = null;
        try {
            sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }

        OkHttpClient client = new OkHttpClient().newBuilder()
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                .sslSocketFactory(sslSocketFactory, xtm)
                .hostnameVerifier((s, sslSession) -> true)
                .addInterceptor(chain -> {
                    Request request = chain.request();
//                    Request builder = request.newBuilder()
//                            .header("authorization", "TOKEN " + MyApplication.manager.getToken())
//                            .header("channel", "1")
//                            .build();
                    Request.Builder builder = request.newBuilder();
//                            .header("authorization", "TOKEN " + MyApplication.manager.getToken())
                    if (MyApplication.manager.isLogin()) {
                        builder.header("authorization", "TOKEN " + MyApplication.manager.getToken());
                    }
                    builder.header("channel", "1");
                    return chain.proceed(builder.build());
                })
                .addNetworkInterceptor(loggingInterceptor)
                .build();

        Retrofit mRetrofit = new Retrofit.Builder()
                .baseUrl(ApiFactory.BASE_SERVER)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build();
        apiService = mRetrofit.create(ApiService.class);
    }

    private static final class InstanceHolder {
        static final RetrofitHelper INSTANCE = new RetrofitHelper();
    }

    public static RetrofitHelper getInstance() {
        return InstanceHolder.INSTANCE;
    }

//    public static RetrofitHelper getInstance() {
//        if (INSTANCE == null) {
//            synchronized (RetrofitHelper.class) {
//                if (INSTANCE == null) {
//                    INSTANCE = new RetrofitHelper();
//                }
//            }
//        }
//        return INSTANCE;
//    }

    public static ApiService getService() {
        return apiService;
    }

    /**
     * @param observable 被观察者
     * @param subscriber 创建观察者并定义响应事件的行为  通过subscribe订阅 连接观察者和被观察者
     */
    public <T> void execute(Observable<T> observable, Observer<T> subscriber) {
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber);
    }

    public <T> T execute(Observable<T> observable) {
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new MyObserver<T>() {
                    @Override
                    protected void onSuccess(T t) {
                    }

                    @Override
                    protected void onFail(Throwable e) {

                    }
                });

        return null;
    }
}
